package com.livew.framework.fastdfs;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerGroup;
import org.csource.fastdfs.TrackerServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.livew.framework.utils.XTStringUtils;

/**
 * 文件上传处理器
 * 
 * 2016年4月7日
 */
public class DfsHandler {

	private Logger logger = LoggerFactory.getLogger(DfsHandler.class);

	private static DfsHandler dfsHandler;

	/**
	 * 获取实例，单例
	 * 
	 * @param propertiesPath
	 * @return
	 * @throws IOException
	 */
	public static DfsHandler getInstance(String propertiesPath) throws IOException {
		if (dfsHandler == null) {
			dfsHandler = new DfsHandler();
			dfsHandler.init(propertiesPath);
		}
		return dfsHandler;
	}

	private Config config;

	/**
	 * 通过配置文件初始化DFS配置
	 * 
	 * @param path
	 * @return
	 * @throws IOException
	 */
	public void init(String path) throws IOException {
		this.config = new Config();
		List<TrackerServerConfig> trackerConfigs = new ArrayList<TrackerServerConfig>();
		config.setTrackerConfigs(trackerConfigs);
		Properties pps = new Properties();
		InputStream in = getClass().getResourceAsStream(path);
		pps.load(in);
		Enumeration<?> enum1 = pps.propertyNames();// 得到配置文件的名字
		while (enum1.hasMoreElements()) {
			Object element = enum1.nextElement();
			// 当key为空，即 “ = 2000”时，key为空字符串
			String key = element.toString().trim();
			if (XTStringUtils.isBlank(key)) {
				continue;
			}
			// 验证value为空时，getProerty获取的是空字符串
			String value = pps.getProperty(key).trim();
			if (Config.Key.connectTimeout.toString().equals(key)) {
				int connectTimeout = Integer.valueOf(value);
				config.setConnectTimeout(connectTimeout);
			} else if (Config.Key.netWorkTimeout.toString().equals(key)) {
				int netWorkTimeout = Integer.valueOf(value);
				config.setNetWorkTimeout(netWorkTimeout);
			} else if (Config.Key.httpPort.toString().equals(key)) {
				int httpPort = Integer.valueOf(value);
				config.setHttpPort(httpPort);
			} else if (key.startsWith(Config.Key.tracker.toString())) {
				String[] arr = value.split(":");
				if (arr != null && arr.length == 2) {// host 与port
					TrackerServerConfig tsc = new TrackerServerConfig();
					tsc.setHost(arr[0]);
					tsc.setPort(Integer.valueOf(arr[1]));
					trackerConfigs.add(tsc);
				}
			}
		}
	}

	/**
	 * 获取文件服务器连接
	 * 
	 * @return
	 * @throws IOException
	 */
	private Connection getStorageClient() throws IOException {
		// 连接超时的时限，单位为毫秒
		ClientGlobal.setG_connect_timeout(config.getConnectTimeout());
		// 网络超时的时限，单位为毫秒
		ClientGlobal.setG_network_timeout(config.getNetWorkTimeout());
		ClientGlobal.setG_anti_steal_token(false);
		// 字符集
		ClientGlobal.setG_charset("UTF-8");
		ClientGlobal.setG_secret_key(null);
		// HTTP访问服务的端口号
		ClientGlobal.setG_tracker_http_port(config.getHttpPort());
		List<TrackerServerConfig> trackerConfigs = config.getTrackerConfigs();
		// Tracker服务器列表，可以允许有多个TrackerServer
		InetSocketAddress[] tracker_servers = new InetSocketAddress[trackerConfigs.size()];
		for (int i = 0; i < trackerConfigs.size(); i++) {
			TrackerServerConfig tc = trackerConfigs.get(i);
			tracker_servers[i] = new InetSocketAddress(tc.getHost(), tc.getPort());
		}
		ClientGlobal.setG_tracker_group(new TrackerGroup(tracker_servers));

        TrackerClient tracker = new TrackerClient(); 
        TrackerServer trackerServer = tracker.getConnection(); 
        StorageServer storageServer = null;
        StorageClient storageClient = new StorageClient(trackerServer, storageServer);
		Connection con = new Connection();
		con.setStorageClient(storageClient);
		con.setStorageServer(storageServer);
		con.setTrackerServer(trackerServer);
		return con;
	}

	/**
	 * 文件上传，返回String[]，长度为2，第一个元素为groupName，第二个为文件在dfs中的ID（即remoteFileName）
	 * 
	 * @param localPath
	 * @param pairs
	 * @throws Exception
	 * @return
	 */
	public String[] upload(String localPath, NameValuePair[] pairs) throws Exception {
		// StorageClient storageClient = getStorageClient();
		Connection con = getStorageClient();
		if (con == null) {
			return null;
		}
		String[] array = con.getStorageClient().upload_file(localPath, null, pairs);
		if (logger.isDebugEnabled()) {
			logger.debug("组名：" + array[0] + ",路径: " + array[1]);
		}
		close(con);
		return array;
	}

	private void close(Connection con) throws Exception {
		if (con == null) {
			return;
		}
		if (null != con.getStorageServer())
			con.getStorageServer().close();
//		if (null != con.getTrackerServer())
//			con.getTrackerServer().close();
	}

	/**
	 * 文件上传，返回String[]，长度为2，第一个元素为groupName，第二个为文件在dfs中的ID（即remoteFileName）
	 * 
	 * @param localPath
	 * @param pairs
	 * @throws Exception
	 * @return
	 */
	public String[] upload(byte[] fileBuffer) throws Exception {
		// StorageClient storageClient = getStorageClient();
		Connection con = getStorageClient();
		if (con == null) {
			return null;
		}
		String[] array = con.getStorageClient().upload_file(fileBuffer, null, null);
		if (logger.isDebugEnabled()) {
			logger.debug("组名：" + array[0] + ",路径: " + array[1]);
		}
		close(con);
		return array;
	}

	public void delete(String groupName, String remotFileName) throws Exception {
		// StorageClient storageClient = getStorageClient();
		Connection con = getStorageClient();
		if (con == null) {
			return;
		}
		con.getStorageClient().delete_file(groupName, remotFileName);
		close(con);
	}

	/**
	 * 下载
	 * 
	 * @param localPath
	 * @param file
	 */
	public void download(String localPath, String groupName, String remoteFileName, String fileSrcName) {
		Connection con = null;
		try {
			// StorageClient storageClient = getStorageClient();
			con = getStorageClient();
			if (con == null) {
				return;
			}
			byte[] b = con.getStorageClient().download_file(groupName, remoteFileName);
			FileOutputStream fos = new FileOutputStream(localPath + fileSrcName);
			for (int i = 0; i < b.length; i++) {
				fos.write(b[i]);
			}
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				close(con);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 下载
	 * 
	 * @param file
	 * @throws Exception
	 */
	public byte[] getBytes(String groupName, String remoteFileName) throws Exception {
		// StorageClient storageClient = getStorageClient();
		Connection con = getStorageClient();
		if (con == null) {
			return null;
		}
		byte[] bytes = con.getStorageClient().download_file(groupName, remoteFileName);
		close(con);
		return bytes;

	}

	/**
	 * 文件复制
	 * 
	 * @param groupName
	 * @param remoteFileName
	 * @throws Exception
	 * @return
	 */
	public String[] copy(String groupName, String remoteFileName) throws Exception {
//		StorageClient storageClient = getStorageClient();
		Connection con = getStorageClient();
		if (con == null) {
			return null;
		}
		byte[] fileBuffer = con.getStorageClient().download_file(groupName, remoteFileName);
		String[] array = con.getStorageClient().upload_file(fileBuffer, null, null);
		if (logger.isDebugEnabled()) {
			logger.debug("组名：" + array[0] + ",路径: " + array[1]);
		}
		close(con);
		return array;
	}

}
